<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MATLAB 数学生命 - 动态粒子系统</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dat.gui@0.7.7/build/dat.gui.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            overflow: hidden;
            background: #000;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        #container {
            position: relative;
            width: 100vw;
            height: 100vh;
        }
        
        #canvas-container {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        
        #title {
            position: absolute;
            top: 20px;
            left: 0;
            width: 100%;
            text-align: center;
            color: rgba(255, 255, 255, 0.8);
            font-size: 24px;
            text-shadow: 0 0 10px rgba(173, 216, 230, 0.7);
            z-index: 10;
            pointer-events: none;
        }
        
        #info {
            position: absolute;
            bottom: 20px;
            left: 0;
            width: 100%;
            text-align: center;
            color: rgba(255, 255, 255, 0.6);
            font-size: 14px;
            z-index: 10;
            pointer-events: none;
        }
        
        #control-panel {
            position: absolute;
            top: 20px;
            right: 20px;
            z-index: 20;
            background: rgba(0, 30, 60, 0.7);
            border-radius: 10px;
            padding: 15px;
            color: white;
            max-width: 300px;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(173, 216, 230, 0.3);
            box-shadow: 0 0 20px rgba(173, 216, 230, 0.2);
        }
        
        #control-panel h3 {
            text-align: center;
            margin-bottom: 15px;
            color: #add8e6;
            border-bottom: 1px solid rgba(173, 216, 230, 0.3);
            padding-bottom: 8px;
        }
        
        .control-group {
            margin-bottom: 15px;
        }
        
        .control-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 8px;
        }
        
        .control-row label {
            flex: 1;
            font-size: 14px;
        }
        
        .control-row input {
            width: 100px;
            background: rgba(30, 60, 90, 0.7);
            border: 1px solid rgba(173, 216, 230, 0.3);
            border-radius: 4px;
            color: white;
            padding: 4px 8px;
        }
        
        button {
            width: 100%;
            padding: 8px;
            background: linear-gradient(to bottom, #87ceeb, #4682b4);
            border: none;
            border-radius: 4px;
            color: white;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
            margin-top: 5px;
        }
        
        button:hover {
            background: linear-gradient(to bottom, #b0e2ff, #5d9fc6);
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(173, 216, 230, 0.4);
        }
        
        @media (max-width: 768px) {
            #control-panel {
                top: 10px;
                right: 10px;
                padding: 10px;
                max-width: 250px;
            }
            
            #title {
                font-size: 18px;
            }
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="canvas-container"></div>
        <div id="title">MATLAB 数学生命 - 动态粒子系统</div>
        <div id="info">基于粒子系统的幽灵动画 | 使用Three.js渲染 </div>
        
        <div id="control-panel">
            <h3>粒子控制系统</h3>
            <div class="control-group">
                <div class="control-row">
                    <label for="size">粒子大小:</label>
                    <input type="range" id="size" min="0.5" max="5" step="0.1" value="1.5">
                </div>
                <div class="control-row">
                    <label for="opacity">透明度:</label>
                    <input type="range" id="opacity" min="0.1" max="1" step="0.05" value="0.5">
                </div>
                <div class="control-row">
                    <label for="speed">动画速度:</label>
                    <input type="range" id="speed" min="0.1" max="2" step="0.1" value="10">
                </div>
            </div>
            <div class="control-group">
                <div class="control-row">
                    <label for="colorR">颜色 R:</label>
                    <input type="range" id="colorR" min="0" max="255" value="240">
                </div>
                <div class="control-row">
                    <label for="colorG">颜色 G:</label>
                    <input type="range" id="colorG" min="0" max="255" value="255">
                </div>
                <div class="control-row">
                    <label for="colorB">颜色 B:</label>
                    <input type="range" id="colorB" min="0" max="255" value="255">
                </div>
            </div>
            <button id="resetBtn">重置参数</button>
        </div>
    </div>

    <script>
        // 初始化Three.js场景（背景改为纯黑色）
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0x000000); // 纯黑色背景
        
        // 创建相机
        const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 3000);
        camera.position.z = 1800;
        
        // 创建渲染器
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        document.getElementById('canvas-container').appendChild(renderer.domElement);
        
        // 粒子系统参数 - 幽灵色设置
        const particleCount = 10001;
        let particleSize = 1.5;
        let particleOpacity = 0.5;
        let animationSpeed = 5.0;
        let particleColor = new THREE.Color(240/255, 255/255, 255/255); // 幽灵色
        
        // 创建粒子几何体和材质
        const particlesGeometry = new THREE.BufferGeometry();
        const positions = new Float32Array(particleCount * 3);
        const colors = new Float32Array(particleCount * 3);
        
        // 初始化粒子颜色为幽灵色
        for (let i = 0; i < particleCount; i++) {
            const idx = i * 3;
            positions[idx] = 0;
            positions[idx + 1] = 0;
            positions[idx + 2] = 0;
            
            colors[idx] = particleColor.r;
            colors[idx + 1] = particleColor.g;
            colors[idx + 2] = particleColor.b;
        }
        
        particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        
        // 粒子材质
        const particlesMaterial = new THREE.PointsMaterial({
            size: particleSize,
            vertexColors: true,
            transparent: true,
            opacity: particleOpacity,
            sizeAttenuation: false,
            blending: THREE.AdditiveBlending,
            depthWrite: false
        });
        
        const particles = new THREE.Points(particlesGeometry, particlesMaterial);
        scene.add(particles);
        
        // 预计算常量数组
        const indices = Array.from({ length: particleCount }, (_, i) => i);
        const x = indices.map(i => i % 200);
        const y = indices.map(i => i / 43);
        const k = indices.map(i => 5 * Math.cos(x[i] / 14) * Math.cos(y[i] / 30));
        const e = indices.map(i => y[i] / 8 - 13);
        const d = indices.map(i => (k[i] * k[i] + e[i] * e[i]) / 59 + 4);
        const a = indices.map(i => Math.atan2(k[i], e[i]));
        
        // 动画变量
        let t = 0;
        
        // 缩放和位置调整
        const scaleFactor = 5;
        const centerOffsetX = 0;
        const centerOffsetY = 300;
        
        // 动画函数（移除星空相关逻辑）
        function animate() {
            requestAnimationFrame(animate);
            
            // 更新粒子位置
            const positions = particlesGeometry.attributes.position.array;
            for (let i = 0; i < particleCount; i++) {
                const idx = i * 3;
                const q = 60 - 3 * Math.sin(a[i] * e[i]) + 
                          k[i] * (3 + 4 / d[i] * Math.sin(d[i] * d[i] - t * 2));
                const c = d[i] / 2 + e[i] / 99 - t / 18;
                const originalX = q * Math.sin(c);
                const originalY = (q + d[i] * 9) * Math.cos(c);
                
                positions[idx] = originalX * scaleFactor + centerOffsetX;
                positions[idx + 1] = originalY * scaleFactor + centerOffsetY;
            }
            particlesGeometry.attributes.position.needsUpdate = true;
            
            t += 0.02 * animationSpeed;
            renderer.render(scene, camera);
        }
        animate();
        
        // 窗口大小调整
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });
        
        // 控制面板交互（移除星空相关控件逻辑）
        document.getElementById('size').addEventListener('input', (e) => {
            particleSize = parseFloat(e.target.value);
            particlesMaterial.size = particleSize;
        });
        
        document.getElementById('opacity').addEventListener('input', (e) => {
            particleOpacity = parseFloat(e.target.value);
            particlesMaterial.opacity = particleOpacity;
        });
        
        document.getElementById('speed').addEventListener('input', (e) => {
            animationSpeed = parseFloat(e.target.value);
        });
        
        // 颜色控制
        const updateColor = () => {
            const r = parseInt(document.getElementById('colorR').value) / 255;
            const g = parseInt(document.getElementById('colorG').value) / 255;
            const b = parseInt(document.getElementById('colorB').value) / 255;
            
            particleColor = new THREE.Color(r, g, b);
            const colors = particlesGeometry.attributes.color.array;
            for (let i = 0; i < particleCount; i++) {
                const idx = i * 3;
                colors[idx] = r;
                colors[idx + 1] = g;
                colors[idx + 2] = b;
            }
            particlesGeometry.attributes.color.needsUpdate = true;
        };
        
        document.getElementById('colorR').addEventListener('input', updateColor);
        document.getElementById('colorG').addEventListener('input', updateColor);
        document.getElementById('colorB').addEventListener('input', updateColor);
        
        // 重置按钮（移除星空相关参数）
        document.getElementById('resetBtn').addEventListener('click', () => {
            document.getElementById('size').value = 1.5;
            document.getElementById('opacity').value = 0.5;
            document.getElementById('speed').value = 10;
            document.getElementById('colorR').value = 240;
            document.getElementById('colorG').value = 255;
            document.getElementById('colorB').value = 255;
            
            particleSize = 1.5;
            particleOpacity = 0.5;
            animationSpeed = 5.0;
            particleColor = new THREE.Color(240/255, 255/255, 255/255);
            
            particlesMaterial.size = particleSize;
            particlesMaterial.opacity = particleOpacity;
            updateColor();
        });
    </script>
</body>
</html>